package org.jeecg.modules.service.wx;

import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.modules.doctor.entity.Doctor;
import org.jeecg.common.modules.doctor.entity.DoctorAssistantRelation;
import org.jeecg.common.modules.doctor.entity.DoctorConfig;
import org.jeecg.common.modules.doctor.entity.DoctorWxUserinfoRelation;
import org.jeecg.common.modules.doctor.service.*;
import org.jeecg.common.modules.group.entity.GroupId;
import org.jeecg.common.modules.group.service.IGroupIdService;
import org.jeecg.common.modules.im.ImService;
import org.jeecg.common.modules.patient.entity.Patient;
import org.jeecg.common.modules.wx.entity.WxUserinfo;
import org.jeecg.common.util.enums.BusinessTypeEnum;
import org.jeecg.common.util.enums.SexEnum;
import org.jeecg.common.util.tencent.request.ChatSystemMsgRequest;
import org.jeecg.common.util.tencent.request.CreateGroupRequest;
import org.jeecg.common.util.tencent.request.MemberRequest;
import org.jeecg.common.util.tencent.response.IMBaseResponse;
import org.jeecg.common.util.wx.WxUrlConvert;
import org.jeecg.modules.config.CustomProperties;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.weixin4j.spring.WeixinTemplate;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import static org.jeecg.common.util.constants.WxConstants.DOCTOR_QRCODE_PRE;
import static org.jeecg.common.util.constants.WxConstants.WX_DOCTOR_QRCODE_PRE;

/**
 * @author guoyh
 * @ClassName QrcodeService
 * @Description
 * @since 2020/8/23 17:21
 **/
@Service
@Slf4j
public class QrcodeService {

    @Resource
    private IDoctorService doctorService;
    @Resource
    private IDoctorPatientRelationService doctorPatientRelationService;
    @Resource
    private IDoctorWxUserinfoRelationService doctorWxUserinfoRelationService;
    @Resource
    private ImService imService;
    @Resource
    private IDoctorAssistantRelationService doctorAssistantRelationService;
    @Resource
    private IDoctorConfigService doctorConfigService;
    @Resource
    private IGroupIdService groupIdService;
    @Resource
    private WeixinTemplate weixinTemplate;
    @Resource
    private CustomProperties customProperties;

    @Async
    public void qrcode(String qrcode, Patient patient, WxUserinfo wxUserinfo){
        // DOC_QRCODE_1294679333098799106
        String doctorId ;
        if (qrcode.startsWith(DOCTOR_QRCODE_PRE)){
            doctorId = qrcode.replace(DOCTOR_QRCODE_PRE,"");
        }else if (qrcode.startsWith(WX_DOCTOR_QRCODE_PRE)){
            doctorId = qrcode.replace(WX_DOCTOR_QRCODE_PRE,"");
        }else{
            log.error("未知的二维码{}",qrcode);
            return;
        }
        log.info("扫码事件，绑定医患关系开始：,患者id：{},医生id：{}",patient.getId(),doctorId);
        Doctor doctor = doctorService.getById(doctorId);
        if (Objects.nonNull(doctor)){
            //【一】初始化医生和患者关系
            doctorPatientRelationService.initRelation(doctorId,patient.getId());

            //【二】初始化医生和微信用户的关系
            DoctorWxUserinfoRelation wxUserinfoRelation = doctorWxUserinfoRelationService.getByDoctorAndOpenid(doctorId,wxUserinfo.getOpenid());
            if(Objects.isNull(wxUserinfoRelation)){
                wxUserinfoRelation = doctorWxUserinfoRelationService.initRelation(doctorId,wxUserinfo.getOpenid(),null);
            }

            //【三】获取聊天室id，并发送系统消息
            String groupId = wxUserinfoRelation.getImGroupId();
            if (StringUtils.isBlank(wxUserinfoRelation.getImGroupId())){
                //（1）提交用户信息到腾讯IM
                imService.importAccount(wxUserinfo.getId(),wxUserinfo.getNickname(),wxUserinfo.getHeadimgurl());

                //（2）提交聊天室成员信息组到腾讯IM
                CreateGroupRequest request = buildGroupRequest(wxUserinfo,doctor);
                IMBaseResponse createRes = imService.createGroup(request);

                if(createRes.getActionStatus().equals("OK")){ //创建成功
                    //（3）更新医生用户关系表im_group_id
                    wxUserinfoRelation.setImGroupId(request.getGroupId());
                    doctorWxUserinfoRelationService.updateById(wxUserinfoRelation);

                    //（4）发送IM消息到医生、用户
                    sendMsg(request.getGroupId(),doctorId);
                }else{
                    //聊天室创建失败，存储失败状态和原因
                    GroupId groupIdObj = groupIdService.getById(request.getGroupId());
                    groupIdObj.setStatus(createRes.getErrorCode());
                    groupIdObj.setError(createRes.getErrorInfo());
                    groupIdService.updateById(groupIdObj);
                }
            }

            //发送IM消息到医生、用户
            sendMsg(groupId,doctorId);

            //【四】提醒消息：患者完善信息
            if (StringUtils.isBlank(patient.getMobile())){
                try {
                    String url = String.format("%s/auth?url=%s/addpaint/%s?token=",customProperties.getH5ApiDomain(), customProperties.getH5Domain(),patient.getId());
                    log.info(String.format("消息的url是：%s",url));
                    url = WxUrlConvert.convertUrl(url,weixinTemplate.getAppId());
                    String content = String.format("您已成功关注\""+buildDoctor(doctor)+"\",请完善个人信息，方便医生调阅\n<a href=\"%s\">>>点击完善个人信息</a>",url);
                    weixinTemplate.message().customSendContent(wxUserinfo.getOpenid(),content);
                } catch (Exception e) {
                    log.error("发送模板消息失败",e);
                }
            }
        }
    }

    private String buildDoctor(Doctor doctor){
        if (StringUtils.isBlank(doctor.getName())){
            return "医生";
        }
        StringBuffer sb = new StringBuffer(doctor.getName());
        if (StringUtils.isNotBlank(doctor.getTitle())){
            sb.append(doctor.getTitle());
        }
        return sb.toString();
    }

    /**
     * IM消息：通知到医生和患者
     * @param groupId
     * @param doctorId
     */
    public void sendMsg(String groupId,String doctorId){
        DoctorConfig doctorConfig = doctorConfigService.getByDoctorId(doctorId,true);
        //给医生发系统消息
        ChatSystemMsgRequest doctorRequest = new ChatSystemMsgRequest();
        doctorRequest.setGroupId(groupId);
        doctorRequest.setContent("Ta关注了您的工作室");
        doctorRequest.setToMembersAccount(Lists.newArrayList(doctorId));
        imService.sendSysMsg(doctorRequest);

        //给患者发系统消息
        ChatSystemMsgRequest patientRequest = new ChatSystemMsgRequest();
        patientRequest.setGroupId(groupId);
        patientRequest.setContent("您关注了医生");
        patientRequest.setToMembersAccount(Lists.newArrayList(doctorId));
        imService.sendSysMsg(patientRequest);

        //给患者发医生自定义的欢迎语
        if (StringUtils.isNotBlank(doctorConfig.getWelcomeText())){
            imService.sendMsg(doctorId,groupId,doctorConfig.getWelcomeText());
        }
    }

    private static final String FACE_URL_TEMPLATE = "%s/r/%s";
    private CreateGroupRequest buildGroupRequest(WxUserinfo patient,Doctor doctor){
        CreateGroupRequest request = new CreateGroupRequest();

        //【一】创建group_id表数据
        GroupId groupId = new GroupId();
        groupId.setName(patient.getNickname());
        groupIdService.save(groupId);

        //【二】组织聊天室成员（医生、助理、患者）的请求数据组
        request.setGroupId(String.valueOf(groupId.getId()));
        request.setName(getGroupName(patient));
        if (StringUtils.isNotBlank(patient.getHeadimgurl())){
            request.setFaceUrl(String.format(FACE_URL_TEMPLATE,customProperties.getApiDomain(),patient.getId()));
        }
        List<DoctorAssistantRelation> allReleations = doctorAssistantRelationService.queryByDoctorId(doctor.getId());
        List<Doctor> doctors = allReleations.stream().map(item -> doctorService.getById(item.getAssistantId())).collect(Collectors.toList());
        doctors.add(doctor); //医生、助理信息数据集合

        List<MemberRequest> members = doctors.stream().map(item -> buildMemberRequest(item,doctor.getId())).collect(Collectors.toList());
        members.add(buildMemberRequest(patient)); //医生、助理、患者信息集合
        request.setOwnerAccount(doctor.getId());  //设置群主
        request.setMemberList(members);
        return request;
    }

    private MemberRequest buildMemberRequest(WxUserinfo wxUserinfo){
        MemberRequest request = new MemberRequest();
        request.setMemberAccount(wxUserinfo.getId());
        MemberRequest.MemberDefineData memberDefineData = new MemberRequest.MemberDefineData();
        memberDefineData.setKey("business");
        memberDefineData.setValue(BusinessTypeEnum.PATIENT.getId().toString());
        request.setAppMemberDefinedData(Lists.newArrayList(memberDefineData));
        return request;
    }

    private MemberRequest buildMemberRequest(Doctor doctor,String doctorId){
        MemberRequest request = new MemberRequest();
        request.setMemberAccount(doctor.getId());
        MemberRequest.MemberDefineData memberDefineData = new MemberRequest.MemberDefineData();
        memberDefineData.setKey("business");
        memberDefineData.setValue(doctor.getBusinessType().toString());
//        if (!StringUtils.equals(doctorId,doctor.getId())){
//            request.setRole(GroupMemberRole.ADMIN.getRole());
//        }
        request.setAppMemberDefinedData(Lists.newArrayList(memberDefineData));
        return request;
    }

    /**
     * 设置聊天群组名称
     * @param wxUserinfo
     * @return
     */
    private String getGroupName(WxUserinfo wxUserinfo){
        StringBuffer sb = new StringBuffer();
        if (StringUtils.isNotBlank(wxUserinfo.getNickname())){
            String name = this.subGroupName(wxUserinfo.getNickname());
            sb.append(name);
        }
        if (Objects.nonNull(wxUserinfo.getSex())){
            sb.append("  ");
            sb.append(SexEnum.getInstance(wxUserinfo.getSex()).getDesc());
        }
        if (StringUtils.isBlank(sb.toString())){
            sb.append(wxUserinfo.getId());
        }
        return sb.toString();
    }

    /**
     * 按字节截取字符串
     */
    public String subGroupName(String name){
        int target = 20; //目标字节
        if(this.getByteLength(name) <= target){
            return name;
        }else{
            int cutBytes = 20;
            if(name == null || "".equals(name.trim())) {
                return "";
            }

            int lastIndex = 0;
            boolean stopFlag = false;

            int totalBytes = 0;
            for(int i=0; i<name.length(); i++) {
                String s = Integer.toBinaryString(name.charAt(i));
                if(s.length() > 8) {
                    totalBytes += 3;
                } else {
                    totalBytes += 1;
                }

                if(!stopFlag) {
                    if(totalBytes == cutBytes) {
                        lastIndex = i;
                        stopFlag = true;
                    } else if(totalBytes > cutBytes) {
                        lastIndex = i - 1;
                        stopFlag = true;
                    }
                }
            }

            if(!stopFlag) {
                return name+"...";
            } else {
                return name.substring(0, lastIndex + 1)+"...";
            }
        }
    }

    /**
     * 获取字符串的字节数
     * @param name
     * @return
     */
    public static int getByteLength(String name) {
        byte[] buff = name.getBytes();
        return buff.length;
    }

}
